package com.cofdet.modbusdebugger;

import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.Spinner;
import android.widget.TextView;


import java.io.IOException;
import java.lang.ref.WeakReference;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.Toast;

public class FuncTcpServer extends AppCompatActivity {
          private Button btnConn,btnClose, btnClr, btnSend;
          private TextView tvDisp;
          private EditText etIP, etSend,editServerPort, etAdr, etFun, etData0;
          private RadioButton rbAdr, rbFun, rbData0, rbCRC, rbLRC, rbAscMode,rbAscAffix,
                  rbHexSend,rbRcvDispAll, rbHexRcv;
          private Spinner spWorkMode;

          int WorkMode = WORK_MODE_TCP_SERVER; //工作模式,定义为:
          private static final int WORK_MODE_TCP_SERVER = 0, WORK_MODE_TCP_CLIENT = 1,
                                   WORK_MODE_UTP_SERVER = 2, WORK_MODE_UTP_CLIENT = 3;

          private ModbusCfg modbusCfg;

          private static TcpServer tcpServer = null;
          private static TcpClient tcpClient = null;
          private static UdpServer udpServer = null;
          private static UdpClient udpClient = null;

          private MyBtnClicker myBtnClicker = new MyBtnClicker();
          private final MyHandler myHandler = new MyHandler(this);
          private MyBroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();
          @SuppressLint("StaticFieldLeak")
          public static Context context;
          ExecutorService exec = Executors.newCachedThreadPool();

          //-----------------------------------------接收数据响应------------------------------------
          private class MyHandler extends android.os.Handler{
                    private final WeakReference<FuncTcpServer> mActivity;
                    MyHandler(FuncTcpServer activity){
                              mActivity = new WeakReference<FuncTcpServer>(activity);
                    }

                    @Override
                    public void handleMessage(Message msg) {
                              FuncTcpServer activity = mActivity.get();
                              if (activity == null) return;

                              String Str = msg.obj.toString();
                              if(Str.indexOf(Str.length() - 1) != '\n') //无换行时，强制增加换行符
                                  Str += '\n';

                              switch (msg.what){
                                  case 1:
                                  case 2:    
                                      tvDisp.append(Str);
                                      if (tvDisp.getLineCount() > tvDisp.getLineHeight()) {//超出屏幕自动滚动显示
                                          int offset = tvDisp.getLineCount() * tvDisp.getLineHeight();
                                          tvDisp.scrollTo(0, offset - tvDisp.getHeight() + tvDisp.getLineHeight());
                                      }
                                      break;
                              }
                    }
          }

          private class MyBroadcastReceiver extends BroadcastReceiver{
                    @Override
                    public void onReceive(Context context, Intent intent) {
                              String mAction = intent.getAction();
                              switch (mAction){
                                        case "tcpServerReceiver":
                                                  String msg = intent.getStringExtra("tcpServerReceiver");
                                                  Message message = Message.obtain();
                                                  message.what = 1;
                                                  message.obj = msg;
                                                  myHandler.sendMessage(message);
                                                  break;
                              }
                    }
          }

          private void bindReceiver(){
                    IntentFilter intentFilter = new IntentFilter("tcpServerReceiver");
                    registerReceiver(myBroadcastReceiver,intentFilter);
          }
          //-----------------------------------------设置modbus参数----------------------------------
          private void updateModbusCfgPara(){
              //设置modbus地址
              String str_data = etAdr.getText().toString();
              if(TextUtils.isEmpty(str_data) || (str_data.trim().length() == 0)){
                  str_data = "0";
              }
              modbusCfg.ModbusAdr = Integer.parseInt(str_data);
              //设置功能码
              str_data = etFun.getText().toString();
              if(TextUtils.isEmpty(str_data) || (str_data.trim().length() == 0)){
                  str_data = "0";
              }
              modbusCfg.FunCode = Integer.parseInt(str_data);
              //设置数据0
              str_data = etData0.getText().toString();
              if(TextUtils.isEmpty(str_data) || (str_data.trim().length() == 0)){
                  str_data = "0";
              }
              modbusCfg.SubFunCode = Integer.parseInt(str_data);
          }
          //--------------------------------根据模式启动,停止与发送服务--------------------------------
          private boolean startService(){
              if(WorkMode == WORK_MODE_TCP_SERVER) {
                  tcpServer = new TcpServer(getPort(), modbusCfg);
                  exec.execute(tcpServer);//最后启动
              }
              else if(WorkMode == WORK_MODE_TCP_CLIENT){
                  final String IP = getIp();
                  if(IP == null) return false;
                  tcpClient = new TcpClient(IP, getPort(), modbusCfg);
                  exec.execute(tcpClient);
              }
              else if(WorkMode == WORK_MODE_UTP_SERVER) {
                  final String IP = getIp();
                  if(IP == null) return false;
                  //新的线程
                  udpServer = new UdpServer(IP,getPort(),modbusCfg);
                  Thread thread = new Thread(udpServer);
                  thread.start();
              }
              else if(WorkMode == WORK_MODE_UTP_CLIENT) {
                  final String IP = getIp();
                  if(IP == null) return false;
                  //建立线程池
                  ExecutorService exec = Executors.newCachedThreadPool();
                  udpClient = new UdpClient(IP,getPort(),modbusCfg);
                  exec.execute(udpClient);
              }
              return true;
          }
          private void stopService(){
              if(WorkMode == WORK_MODE_TCP_SERVER) {
                  tcpServer.closeSelf();
              }
              else if(WorkMode == WORK_MODE_TCP_CLIENT) {
                  tcpClient.closeSelf();
              }
              else if(WorkMode == WORK_MODE_UTP_SERVER) {
                  final Thread thread = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          udpServer.setUdpLife(false);//关闭UDP
                          while (udpServer.IsUdpLifeOver()); //等待udp阻塞结束，这里就体现出超时的好处了
                          Looper.getMainLooper();
                      }
                  });
                  thread.start();
              }
              else if(WorkMode == WORK_MODE_UTP_CLIENT) {
                  final Thread thread = new Thread(new Runnable() {
                      @Override
                      public void run() {
                          udpClient.setUdpLife(false);//关闭UDP
                          while (udpClient.IsUdpLifeOver()) ; //等待udp阻塞结束，这里就体现出超时的好处了
                          Looper.getMainLooper();
                      }
                  });
                  thread.start();
              }
          }
          private boolean IsEnSendData() {
              final String Str = etSend.getText().toString();
              if (Str == null) return false;
              if (WorkMode == WORK_MODE_TCP_SERVER) {
                  if (!tcpServer.haveSlv()) return false; //有从机时才能发送
              }
              else if (WorkMode == WORK_MODE_UTP_SERVER) {
                  if (!udpServer.haveSlv()) return false; //有从机时才能发送
              }
              return true;
          }

          private void SendData(){
              final String Str = etSend.getText().toString();
              Message message = Message.obtain();
              message.what = 2;
              message.obj = "Tx: " + Str;
              myHandler.sendMessage(message);
              if(WorkMode == WORK_MODE_TCP_SERVER) {
                  exec.execute(new Runnable() {
                            public void run() {//通讯发出
                                tcpServer.SST.get(0).send(Str);
                            }
                  });
              }
              else if(WorkMode == WORK_MODE_TCP_CLIENT) {
                  exec.execute(new Runnable() {
                      @Override
                      public void run() {//通讯发出
                          tcpClient.send(Str);
                      }
                  });
              }
              else if(WorkMode == WORK_MODE_UTP_SERVER) {
                  exec.execute(new Runnable() {
                      @Override
                      public void run() {//通讯发出
                          udpServer.Send(Str);
                      }
                  });
              }
              else if(WorkMode == WORK_MODE_UTP_CLIENT) {
                  exec.execute(new Runnable() {
                      @Override
                      public void run() {//通讯发出
                          udpClient.send(Str);
                      }
                  });
              }
          }

         //-----------------------------------------点击响应-----------------------------------------
          private class MyBtnClicker implements View.OnClickListener{
                    @Override
                    public void onClick(View view) {
                              switch (view.getId()){
                                        case R.id.btnConn:
                                                  if(startService()  == false) break;
                                                  //启动成功时,同步按钮
                                                  spWorkMode.setEnabled(false);
                                                  btnConn.setEnabled(false);
                                                  btnClose.setEnabled(true);
                                                  btnSend.setEnabled(true);
                                                  editServerPort.setEnabled(false);
                                                  etIP.setEnabled(false);
                                                  Log.i("A", "onClick: 开始");
                                                  break;
                                        case R.id.btnClose:
                                                  stopService(); //先停止
                                                  //同步按钮
                                                  spWorkMode.setEnabled(true);
                                                  btnConn.setEnabled(true);
                                                  btnClose.setEnabled(false);
                                                  btnSend.setEnabled(false);
                                                  editServerPort.setEnabled(false);
                                                  updateWorkModeAbout();

                                                  break;
                                        case R.id.btnClr:
                                                  tvDisp.setText("");
                                                  break;
                                        case R.id.btnSend:
                                                  updateModbusCfgPara();
                                                  if(!IsEnSendData()) {//未准备好
                                                      break;
                                                  }
                                                  SendData();
                                                  break;
                                        case R.id.rbAdr:
                                            if(modbusCfg.isAddAdr){
                                                modbusCfg.isAddAdr = false;
                                                rbAdr.setChecked(false);
                                            }
                                            else{
                                                modbusCfg.isAddAdr = true;
                                                rbAdr.setChecked(true);
                                            }
                                            etAdr.setEnabled(rbAdr.isChecked());
                                            break;
                                        case R.id.rbFun:
                                            if(modbusCfg.isAddFunCode){
                                                modbusCfg.isAddFunCode = false;
                                                rbFun.setChecked(false);
                                            }
                                            else{
                                                modbusCfg.isAddFunCode = true;
                                                rbFun.setChecked(true);
                                            }
                                             etFun.setEnabled(rbFun.isChecked());
                                            break;
                                        case R.id.rbData0:
                                            if(modbusCfg.isAddSubFunCode){
                                                modbusCfg.isAddSubFunCode = false;
                                                rbData0.setChecked(false);
                                            }
                                            else{
                                                modbusCfg.isAddSubFunCode = true;
                                                rbData0.setChecked(true);
                                            }
                                            etData0.setEnabled(rbData0.isChecked());
                                            break;
                                        case R.id.rbCRC:
                                            if(modbusCfg.isAddCRC){
                                                modbusCfg.isAddCRC = false;
                                                rbCRC.setChecked(false);
                                            }
                                            else{//CRC了
                                                modbusCfg.isAddCRC = true;
                                                rbCRC.setChecked(true);
                                                //预置为正确格式
                                                modbusCfg.isAddLRC = false;
                                                rbLRC.setChecked(false);
                                                modbusCfg.isAscMode = false;
                                                rbAscMode.setChecked(false);
                                                modbusCfg.isAscAffix = false;
                                                rbAscAffix.setChecked(false);
                                            }
                                            break;
                                        case R.id.rbLRC:
                                            if(modbusCfg.isAddLRC){
                                                modbusCfg.isAddLRC = false;
                                                rbLRC.setChecked(false);
                                            }
                                            else{//LRC了
                                                modbusCfg.isAddLRC = true;
                                                rbLRC.setChecked(true);
                                                //预置为正确格式
                                                modbusCfg.isAddCRC = false;
                                                rbCRC.setChecked(false);
                                                modbusCfg.isAscMode = true;
                                                rbAscMode.setChecked(true);
                                                modbusCfg.isAscAffix = true;
                                                rbAscAffix.setChecked(true);
                                                modbusCfg.isHexSend = true;
                                                rbHexSend.setChecked(true);
                                            }
                                            break;
                                        case R.id.rbAscMode:
                                            if(modbusCfg.isAscMode){
                                                modbusCfg.isAscMode = false;
                                                rbAscMode.setChecked(false);
                                            }
                                            else{
                                                modbusCfg.isAscMode = true;
                                                rbAscMode.setChecked(true);
                                            }
                                            break;
                                        case R.id.rbAscAffix:
                                            if(modbusCfg.isAscAffix){
                                                modbusCfg.isAscAffix = false;
                                                rbAscAffix.setChecked(false);
                                            }
                                            else{
                                                modbusCfg.isAscAffix = true;
                                                rbAscAffix.setChecked(true);
                                            }
                                            break;
                                        case R.id.rbHexSend:
                                            if(modbusCfg.isHexSend){
                                                modbusCfg.isHexSend = false;
                                                rbHexSend.setChecked(false);
                                            }
                                            else{
                                                modbusCfg.isHexSend = true;
                                                rbHexSend.setChecked(true);
                                            }
                                            break;
                                  case R.id.rbHexRcv:
                                      if(modbusCfg.isHexRcv){
                                          modbusCfg.isHexRcv = false;
                                          rbHexRcv.setChecked(false);
                                      }
                                      else{
                                          modbusCfg.isHexRcv = true;
                                          rbHexRcv.setChecked(true);
                                      }
                                      break;
                                        case R.id.rbRcvDispAll:
                                            if(modbusCfg.isRcvDispAll){
                                                modbusCfg.isRcvDispAll = false;
                                                rbRcvDispAll.setChecked(false);
                                            }
                                            else{
                                                modbusCfg.isRcvDispAll = true;
                                                rbRcvDispAll.setChecked(true);
                                            }
                                            break;
                              }
                    }
          }

    //-----------------------------------------初始化相关-----------------------------------------
          protected void onCreate(Bundle savedInstanceState) {
                    super.onCreate(savedInstanceState);
                    getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);//输入法上移
                    setContentView(R.layout.tcp_server);
                    context = this;
                    modbusCfg = new ModbusCfg();
                    bindID();
                    bindListener();
                    bindReceiver();
                    ini();
          }


          private void ini(){
                    btnClose.setEnabled(false);
                    btnSend.setEnabled(false);
                    updateWorkModeAbout();
          }


          private void bindListener() {
                    btnConn.setOnClickListener(myBtnClicker);
                    btnClose.setOnClickListener(myBtnClicker);
                    btnClr.setOnClickListener(myBtnClicker);
                    btnSend.setOnClickListener(myBtnClicker);

                    rbAdr.setOnClickListener(myBtnClicker);
                    rbFun.setOnClickListener(myBtnClicker);
                    rbData0.setOnClickListener(myBtnClicker);
                    rbCRC.setOnClickListener(myBtnClicker);
                    rbLRC.setOnClickListener(myBtnClicker);
                    rbAscMode.setOnClickListener(myBtnClicker);
                    rbAscAffix.setOnClickListener(myBtnClicker);
                    rbHexSend.setOnClickListener(myBtnClicker);
                    rbHexRcv.setOnClickListener(myBtnClicker);
                    rbRcvDispAll.setOnClickListener(myBtnClicker);
          }

          private void bindID() {
                    btnConn = (Button) findViewById(R.id.btnConn);
                    btnClose = (Button) findViewById(R.id.btnClose);
                    btnClr = (Button) findViewById(R.id.btnClr);
                    btnSend = (Button)findViewById(R.id.btnSend);

                    tvDisp = (TextView) findViewById(R.id.tvDisp);
                    tvDisp.setMovementMethod(ScrollingMovementMethod.getInstance());//允许上下滚动

                    etIP = (EditText) findViewById(R.id.etIP);
                    etAdr = (EditText) findViewById(R.id.etAdr);
                    etAdr.setText("1");
                    etFun = (EditText) findViewById(R.id.etFun);
                    etFun.setText("62");
                    etData0 = (EditText) findViewById(R.id.etData0);
                    etData0.setText("0");
                    etSend = (EditText) findViewById(R.id.etSend);
                    editServerPort = (EditText)findViewById(R.id.etPort);

                    rbAdr = (RadioButton)findViewById(R.id.rbAdr);
                    rbFun = (RadioButton)findViewById(R.id.rbFun);
                    rbData0 = (RadioButton)findViewById(R.id.rbData0);
                    rbCRC = (RadioButton)findViewById(R.id.rbCRC);
                    rbLRC = (RadioButton)findViewById(R.id.rbLRC);
                    rbAscMode = (RadioButton)findViewById(R.id.rbAscMode);
                    rbAscAffix = (RadioButton)findViewById(R.id.rbAscAffix);
                    rbHexSend = (RadioButton)findViewById(R.id.rbHexSend);
                    rbHexRcv = (RadioButton)findViewById(R.id.rbHexRcv);
                    rbRcvDispAll = (RadioButton)findViewById(R.id.rbRcvDispAll);

                    //工作模式初始化
                    spWorkMode = (Spinner)findViewById(R.id.spWorkMode);
                    spWorkMode.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
                          @Override
                          public void onItemSelected(AdapterView<?> parent, View view,
                                                     int pos, long id) {
                              WorkMode = pos;
                              updateWorkModeAbout();

                          }
                          @Override
                          public void onNothingSelected(AdapterView<?> parent) {
                              // Another interface callback
                          }
                    });
          }

    //----------------------------------------更新工作模式相关---------------------------------------
    private void updateWorkModeAbout()
    {
        TextView tvIP = (TextView) findViewById(R.id.tvIP);
        if((WorkMode == WORK_MODE_TCP_SERVER) || (WorkMode == WORK_MODE_UTP_SERVER)) {
            tvIP.setText("本  机IP: ");
            etIP.setText(getHostIP());
            etIP.setEnabled(false);
        }
        else{
            tvIP.setText("服务器IP: ");
            etIP.setEnabled(true);
        }
    }

    //-----------------------------------------获取本机IP与端口--------------------------------------
    private int getPort(){
        String msg = editServerPort.getText().toString();
        if (msg.equals("")){
            msg = "10001";
        }
        return Integer.parseInt(msg);
    }
    private final String getIp() {//无效时返回null
        String msg = etIP.getText().toString();
        if(msg.equals(getHostIP())){
            if((WorkMode == WORK_MODE_UTP_SERVER)){
                return msg;
            }
            Toast toast = Toast.makeText(this,"请输入服务器IP！", Toast.LENGTH_SHORT);
            toast.show();
            return null;
        }

        String rexp = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
        Pattern pat = Pattern.compile(rexp);
        Matcher mat = pat.matcher(msg);
        if (mat.find() == false) {
            Toast toast = Toast.makeText(this,"IP地址格式有误", Toast.LENGTH_SHORT);
            toast.show();
            //etIP.setText("192.168.88.212");//临时
            return null;
        }
        return msg;
    }

    public String getHostIP() {
        String hostIp = null;
        try {
            Enumeration nis = NetworkInterface.getNetworkInterfaces();
            InetAddress ia = null;
            while (nis.hasMoreElements()) {
                NetworkInterface ni = (NetworkInterface) nis.nextElement();
                Enumeration<InetAddress> ias = ni.getInetAddresses();
                while (ias.hasMoreElements()) {
                    ia = ias.nextElement();
                    if (ia instanceof Inet6Address) {
                        continue;// skip ipv6
                    }
                    String ip = ia.getHostAddress();
                    if (!"127.0.0.1".equals(ip)) {
                        hostIp = ia.getHostAddress();
                        break;
                    }
                }
            }
        } catch (SocketException e) {
            Log.i("FuncTcpServer", "SocketException");
            e.printStackTrace();
        }
        return hostIp;


    }



}
